﻿using System;
using System.Collections.Generic;
using System.Linq;
using Fuse8.ContentManagementFramework.BizFacade;
using Fuse8.ContentManagementFramework.Domain;
using Fuse8.ContentManagementFramework.Domain.Special;
using Fuse8.ContentManagementFramework.Web.Etc.PagePresent;
using Fuse8.DomainFramework.Common;

namespace Fuse8.ContentManagementFramework.Web.MvcPowered.Components.Models
{
    [Serializable]
    public class CmsPageComponentItem
    {
        public int PageId { get; set; }

        public string Title { get; set; }

        public string Url { get; set; }

        public bool IsLatest { get; set; }

        public bool IsCurrent { get; set; }

        public bool IsVisible { get; set; }

        public bool IsOpenInNewWindow { get; set; }

        public int Level { get; set; }

        public int PublicPageId { get; set; }

        public CmsPageBehaviourTypeKind PageBehaviourType { get; set; }

        public virtual bool HasChildren
        {
            get
            {
                return ChildPages != null && ChildPages.Any();
            }
        }

        public IEnumerable<CmsPageComponentItem> ChildPages { get; set; }

        public CmsPageComponentItem()
        { }

        public CmsPageComponentItem(CmsPage page)
        {
            Guard.ArgumentNotNull(page, "page");
            
            PageId = page.Id;
            Title = page.PageName;
            Url = CmsUrlManager.GetUrlByPage(page);
            Level = page.PageLevel;
            PublicPageId = page.PublicPageId;
            PageBehaviourType = page.BehaviourPageType;
            if (page.BehaviourPageType == CmsPageBehaviourTypeKind.Redirect)
            {
                IsOpenInNewWindow = page.RedirectSetting.OpenInNewWindow;
            }
        }
    }

    public static class CmsPageComponentItemExtension
    {
        public static IEnumerable<CmsPageComponentItemForNavigation> GetHierarchyFromCollection(this CmsPageComponentItemForNavigation component, IEnumerable<CmsPage> pageCollection, CmsPage currentPage, int maxVisibleLevel)            
        {
            IEnumerable<CmsPageComponentItemForNavigation> result = null;

            if (pageCollection != null)
            {
                var pageList = pageCollection.ToList();
                if (pageList.Any(p => p != null))
                {
                    int minLevel = pageList.Select(p => p.PageLevel).Min();
                    var parentPages = pageList
                        .Where(p => minLevel == 0 ? p.PageLevel <= minLevel + 1 : p.PageLevel == minLevel).ToArray();

                    result = AdoptPages(pageList, currentPage, maxVisibleLevel, parentPages);
                }
            }
            return result ?? new [] { component }.AsEnumerable();
        }

        private static IEnumerable<CmsPageComponentItemForNavigation> AdoptPages(IList<CmsPage> fullCollection, CmsPage currentPage, int maxVisibleLevel, CmsPage[] pages)            
        {
            IEnumerable<CmsPageComponentItemForNavigation> result = null;
            if (pages.Any(p => p != null))
            {
                var latestItem = pages.LastOrDefault();

                var data = pages.SelectMany(
                    p =>
                        {
                            var strategy = PagePresentStrategyFactory.GetStrategy(p);
                            var res = new List<CmsPageComponentItemForNavigation>();
                            foreach (var item in strategy.GetNavigationItems())
                            {
                                if (item.ChildPages == null)
                                {
                                    item.ChildPages = GetNested(p.Id, fullCollection, currentPage, maxVisibleLevel);
                                }
                                else
                                {
                                    item.ChildPages = item.ChildPages.Concat(GetNested(p.Id, fullCollection, currentPage, maxVisibleLevel));
                                }
                                item.IsLatest = latestItem != null && p.Id == latestItem.Id;
                                if (!item.CancelResetCurrentState)
                                {
                                    item.IsCurrent = currentPage != null && p.Id == currentPage.Id;
                                }
                                item.IsVisible = !(maxVisibleLevel > 0) || p.PageLevel <= maxVisibleLevel;
                                res.Add(item);
                            }

                            return res;
                        }
                    ).ToList();

                data.ForEach(p =>
                                 {
                                     if (!p.IsCurrent && (p.Level > 0))
                                     {
                                         p.IsCurrent = p.ChildPages.Any(q => q.IsCurrent);
                                     }
                                 });

                result = data;
            }
            return result;
        }

        private static IEnumerable<CmsPageComponentItemForNavigation> GetNested(int? parentId, IList<CmsPage> pageCollection, CmsPage currentPage, int maxVisibleLevel)            
        {
            IEnumerable<CmsPageComponentItemForNavigation> result = null;

            var children = pageCollection.Where(p => p.ParentPageId == parentId).ToArray();

            result = AdoptPages(pageCollection, currentPage, maxVisibleLevel, children);

            return result ?? new List<CmsPageComponentItemForNavigation>();
        }
    }
}
